package com.quantum.core.components
{
	import com.quantum.core.events.DockingEvent;
	import com.quantum.core.events.LayoutChangeEvent;
	import com.quantum.core.layout.BorderLayout;
	import com.quantum.core.managers.PerspectiveManager;
	import com.quantum.flexutil.KeyedSet;

	import flash.display.DisplayObject;

	import mx.containers.Canvas;
	import mx.core.UIComponent;
	import mx.effects.Move;
	import mx.effects.Parallel;
	import mx.effects.Resize;
	import mx.effects.easing.Exponential;

	public class StageView extends Canvas
	{
		private var parallel:Parallel;
		private var maximizeParallel:Parallel;

		public var items:KeyedSet=new KeyedSet(); // Stores the views which are not minimized.
		public var minimizedItems:KeyedSet=new KeyedSet(); // Stores the minimized views.
		public var maximizedWindow:ViewWindow;
		public var stageWindow:StageWindow;

		public function StageView()
		{
			super();
			addEventListener(DockingEvent.DOCKED, onDockingViewDock);
			addEventListener(DockingEvent.MAXIMIZE, onDockingViewMaximize);
			addEventListener(DockingEvent.MINIMIZE, onDockingViewMinimize);
			addEventListener(DockingEvent.REMOVED, onDockingViewRemoved);
			addEventListener(DockingEvent.RESTORE, onDockingViewRestore);
		}

		public function addView(view:DockingView):void
		{
			var window:ViewWindow=null;
			if (maximizedWindow)
			{
				window=maximizedWindow;
			}
			else if (items.length == 0)
			{
				window=new ViewWindow();
				addChild(window);
				items.add(window);
			}
			else
			{
				window=getViewWindow(this);
			}

			if (!window.contains(view))
			{
				window.addChild(view);
//            window.selectedIndex = window.getChildIndex(view);
			}
		}

		private function getViewWindow(parent:UIComponent):ViewWindow
		{
			var window:ViewWindow=null;
			var child:UIComponent=parent.getChildAt(0) as UIComponent;
			if (child is SplitWindow)
			{
				window=getViewWindow(child);
			}
			else if (child is ViewWindow)
			{
				window=child as ViewWindow;
			}
			return window;
		}

		protected function onDockingViewMinimize(event:DockingEvent):void
		{
			var viewWindow:ViewWindow=event.target as ViewWindow;
			minimizedItems.add(viewWindow);
			items.remove(viewWindow);

			updateLayout();
		}

		private function onDockingViewDock(event:DockingEvent):void
		{
			var viewTab:ViewTab=event.viewTab;
			var originalViewWindow:ViewWindow=viewTab.getViewWindow();
			var targetViewWindow:ViewWindow=event.viewWindow;
			var borderLayout:String=targetViewWindow.borderLayout;

			if (originalViewWindow != targetViewWindow || BorderLayout.CENTER != borderLayout)
			{
				var view:DockingView=originalViewWindow.removeChildAt(viewTab.parent.getChildIndex(viewTab)) as DockingView;
				insertView(view, borderLayout, targetViewWindow);
			}

			event.stopImmediatePropagation();
			event=null;
		}

		private function insertView(view:DockingView, borderLayout:String, targetViewWindow:ViewWindow):void
		{
			if (BorderLayout.CENTER == borderLayout)
			{
				targetViewWindow.addChild(view);
			}
			else
			{
				var newViewWindow:ViewWindow=new ViewWindow();
				newViewWindow.addChild(view);
				items.add(newViewWindow);

				var splitWindow:SplitWindow=new SplitWindow();
				splitWindow.percentWidth=targetViewWindow.percentWidth;
				splitWindow.percentHeight=targetViewWindow.percentHeight;

				splitWindow.direction=BorderLayout.toDirection(borderLayout);

				var parentComponent:UIComponent=targetViewWindow.parent as UIComponent;
				var splitWindowIndex:int=parentComponent.getChildIndex(targetViewWindow);
				parentComponent.removeChild(targetViewWindow);

				parentComponent.addChildAt(splitWindow, splitWindowIndex);

				if (true == splitWindow.isHorizontal())
				{
					if (newViewWindow.originalWidth > 0)
					{
						newViewWindow.width=(splitWindow.width > targetViewWindow.originalWidth) ? newViewWindow.originalWidth : splitWindow.width / 2;
						newViewWindow.percentWidth=(targetViewWindow.width / splitWindow.width) * 100;

						targetViewWindow.percentWidth=100 - targetViewWindow.percentWidth;
					}
					else
					{
						newViewWindow.percentWidth=targetViewWindow.percentWidth;
					}

					newViewWindow.percentHeight=targetViewWindow.percentHeight=100;
				}
				else
				{
					if (newViewWindow.originalHeight > 0)
					{
						newViewWindow.height=(splitWindow.height > targetViewWindow.originalHeight) ? newViewWindow.originalHeight : splitWindow.height / 2;
						newViewWindow.percentHeight=(targetViewWindow.height / splitWindow.height) * 100;

						targetViewWindow.percentHeight=100 - targetViewWindow.percentHeight;
					}
					else
					{
						newViewWindow.percentHeight=targetViewWindow.percentHeight;
					}
					newViewWindow.percentWidth=targetViewWindow.percentWidth=100;
				}
				splitWindow.addChild(targetViewWindow);
				splitWindow.addChildAt(newViewWindow, BorderLayout.childIndex(borderLayout));
			}
		}

		private function onDockingViewMaximize(event:DockingEvent):void
		{

			var window:ViewWindow=ViewWindow(event.target);
			stageWindow.addChild(window);
			maximizeParallel=new Parallel();
			maximizeParallel.duration=1000;
			addResizeAndMoveToParallel(window, maximizeParallel, stageWindow.width, stageWindow.height, 0, 0);
			maximizeParallel.play();

			maximizedWindow=window;

			items.remove(window);
			updateLayout();
		}

		private function onDockingViewRestore(event:DockingEvent):void
		{
			var window:ViewWindow=event.target as ViewWindow;
			items.add(window);
			if (window.windowState == ViewWindow.WINDOW_STATE_MAXIMIZED)
			{
				if (maximizeParallel != null && maximizeParallel.isPlaying)
					maximizeParallel.pause();

				maximizedWindow=null;
				maximizeParallel=new Parallel();
				maximizeParallel.play();
			}
			else
			{
				minimizedItems.remove(window);

				updateLayout();
			}
		}

		public function onDockingViewRemoved(event:DockingEvent):void
		{
			var targetView:DockingView=event.view;
			var targetViewWindow:ViewWindow=event.viewWindow;

			if (targetViewWindow.numChildren == 0)
			{
				items.remove(targetViewWindow);
				targetViewWindow.parent.removeChild(targetViewWindow);
			}
			updateLayout();
		}

		public function clear():void
		{
			removeAllChildren();
			items=new KeyedSet();
		}

		public function updateLayout():void
		{
			var len:Number=items.length;

			includeInLayout=visible=len > 0;
			var window:ViewWindow;

			if (parallel != null && parallel.isPlaying)
				parallel.pause();

			parallel=new Parallel();
			parallel.duration=1000;

			len=minimizedItems.length;
			var minimizedViews:Array=minimizedItems.toArray();
			if (len > 0)
			{
				for (var ii:int=0; ii < len; ii++)
				{
					window=ViewWindow(minimizedViews[ii]);
					addResizeAndMoveToParallel(window, parallel, 0, 0, 0, stageWindow.height);
				}
			}

			if (parallel != null && parallel.children.length > 0)
				parallel.play();

			PerspectiveManager.getInstance().dispatchEvent(new LayoutChangeEvent());
		}

		private function addResizeAndMoveToParallel(target:ViewWindow, parallel:Parallel, widthTo:Number, heightTo:Number, xTo:Number, yTo:Number):void
		{
			var resize:Resize=new Resize(target);
			resize.widthTo=widthTo;
			resize.heightTo=heightTo;
			resize.easingFunction=Exponential.easeOut;
			parallel.addChild(resize);

			var move:Move=new Move(target);
			move.xTo=xTo;
			move.yTo=yTo;
			move.easingFunction=Exponential.easeOut;
			parallel.addChild(move);
		}
	}
}